export {}
// js 函数写法（es6 之前）与基本类型
function funReturnNumber(): number {
    return 1
}
function funReturnString(): string {
    return " "
}
function funReturnArrayString(): Array<string> {
    return [" ", " "]
}
function funReturnMap(): Map<string, string> {
    let myMap = new Map<string, string>();
    myMap.set("ok", "yes");
    return myMap;
}
function funReturnVoid(): void { }
function funReturnBoolean(): boolean {
    return true
}
function funReturnNull(): null {
    return null;
}


/* 
object 不包含 基本类型

let arr:1|'2' = 
    表明arr 只能是 1，或者 '2' 和枚举大同小异
let obj:{a:1}|{b:'2'}
    表明：obj 必须包含 a 或者 b 属性，不能有其他属性

let object:{a:string,b:number}&{c:string}
    表明： object abc三个属性都得有 当一个类型出现多次的时候，参数必须都满足

any类型 ： 绕过 ts检测机制
unknown：有检验！

*/

/*
    ts的lambda函数（es6 箭头函数）
*/
// 不指明返回值
let myVoid = () => {
    console.log(1)
    return 1
}
// 指明返回值
let myMap: () => Map<string, string> =
    function () {
        let m = new Map();
        m.set("os", "ubuntu");
        return m;
    };

/*
    map 类 赋值 读取 遍历 
*/
var myMap2 = new Map();
myMap2.set(0, "zero");
myMap2.set(1, "one");
console.log(myMap2.get(1))
// for ... of 
for (var [key, value] of myMap2) {
    console.log(key + " = " + value);
}
for (var key of myMap2.keys()) {
    console.log(key);
}
for (var value of myMap2.values()) {
    console.log(value);
}
// foreach()
myMap2.forEach(function (value, key) {
    console.log(key + " = " + value);
}, myMap2)

/*
  元组
    {
        可变，
        数据类型可不同
    }
*/
let tuples = ["a", 1, true]
for (var u of tuples) {
    console.log(u)
}
// 元组解构 
var a = [10, "Runoob"]
var [b, c] = a // = > 等价于 var b = a[0], c = a[1];


/*
    数组 Array 
        {
            解构
            遍历
            传参
            多维数组
        }
*/
// 数组解构
var arr: number[] = [12, 13]
var [x, y] = arr // = > 等价于 var x = arr[0], y = arr[1];

// 遍历
for (var j in arr) {
    console.log(arr[j]);
}

// 传参 
function arrayTest(arr: string[]): void {
    for (var j in arr) {
        console.log(arr[j]);
    }
}

// 多维数组
let myManyArray = [[11, 22], [44, 55]]


/*
    枚举类
        枚举类有多重使用方式，此处只列我需要的
*/
enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}

console.log(Direction.Up)

/*
    联合类型 重载思想 建议用枚举类
        let y = string|number

*/

/*
    ts 函数重载
*/
// 声明函数
function getArray(x: number): number[];
function getArray(str: string): string[];
// 实现重载
function getArray(value: any): any[] {
    // todo 使用枚举类对类型判定 ？ 
    if (typeof value === 'string') {
        return value.split('');
    } else {
        // 命名数组的变量的时候必须指明类型（同强语言）
        let arr: Array<number> = [];
        for (let i = 0; i <= value; i++) {
            arr.push(i);
        }
        return arr;
    }
}


/*
  类继承 
      {
        不可继承多个但是可以多继承
      }
          
 */
class Father {
    name: string | undefined;
    setFatherName(name: string): void {
        this.name = name
    }

}
class Son extends Father {
    setFamliyName(name: string): void {
        super.setFatherName(name)
    }
}

/* 
    类 
*/
class Person {
    name: string;
    age: number;
    sex: string;
    // 构造方法
    constructor(name: string, age: number, sex: string) {
        this.name = name
        this.age = age
        this.sex = sex
    }

    go(): void {
        console.log("my name is " + this.name + "性别" + this.sex + "今年" + this.age + "岁了！")
    }

}
let p = new Person('hui', 11, 'man');
console.log(p.go())


/*
    补充方法：
        {
            instanceof ： 判定是否为指定类型 返回true/false
                var obj = new Person() 
                var isPerson = obj instanceof Person; 
        } 
*/


/*
    接口
        {
            接口定义
            接口实现
            接口继承
            接口和联合类型
            
        }
*/

// 接口定义
interface IPerson {
    firstName: string,
    lastName: string,
    sayHi: () => string
}
// 接口实现 ： 转成 js 直接就是 一个 customer 对象，这里接口起到的作用只是校验（类似于抽象类的实现，必须将所有参数，方法都实现！）
let customer: IPerson = {
    firstName: "Tom",
    lastName: "Hanks",
    sayHi: (): string => { return "Hi there" }
}

// 接口继承 : 接口继承可不实现父类的方法，但自己的方法必须实现！ ？标注有问题
interface Person {
    age: number
}
interface Musician extends Person {
    instrument: string
}
var drummer = <Musician>{};
drummer.age = 27
drummer.instrument = "Drums"
console.log("年龄:  " + drummer.age)
console.log("喜欢的乐器:  " + drummer.instrument)

// 接口多继承 
interface IParent1 {
    v1: number
}
interface IParent2 {
    v2: number
}
interface Child extends IParent1, IParent2 { }
var Iobj: Child = { v1: 12, v2: 23 }
console.log("value 1: " + Iobj.v1 + " value 2: " + Iobj.v2)

// 联合类型和接口
interface RunOptions {
    program: string;
    commandline: string[] | string | (() => string);
}
// commandline 是字符串
var options: RunOptions = { program: "test1", commandline: "Hello" };
console.log(options.commandline)
// commandline 是字符串数组
var options1: RunOptions = { program: "test1", commandline: ["Hello", "World"] };
// 这里有问题 ！
// console.log(options.commandline[0]); 
// console.log(options.commandline[1]);  
// commandline 是一个函数表达式
var options2: RunOptions = { program: "test1", commandline: () => { return "**Hello World**"; } };
var fn: any = options2.commandline;
console.log(fn());



/*
    类和接口 
        {
            类可实现接口 
                实现接口必须将所有的方法，参数，一一实现
        }
*/
interface ILoan { 
    interest:number 

    cooo:(()=>Map<string,string>)

} 
  
 class AgriLoan1 implements ILoan { 
    interest:number 
    rebate:number 

    cooo=function(){
        return new Map<string,string>;
    }
    
    constructor(interest:number,rebate:number) { 
       this.interest = interest 
       this.rebate = rebate 
    } 
 } 

// 实际变成的js语句为 ： 
/*
    var AgriLoan =  (function () {
        function AgriLoan(interest, rebate) {
            this.interest = interest;
            this.rebate = rebate;
        }
        return AgriLoan;
    }());
*/


// 
/*
    ts 对象 
        {
            ts对象和js一样，但是ts不可直接用等号赋值，必须要初定义就已经有的元素才可赋值！
        }
*/
var sites = {
    site1: "Runoob",
    site2: "Google",
    sayHello: function () { } // 类型模板
};
sites.sayHello = function () {
    console.log("hello " + sites.site1);
};
sites.sayHello();


/* 
    鸭子类型：duck typing
        "当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子，那么这只鸟就可以被称为鸭子。"
*/
interface IPoint { 
    x:number 
    y:number 
} 
function addPoints(p1:IPoint,p2:IPoint):IPoint { 
    var x = p1.x + p2.x 
    var y = p1.y + p2.y 
    return {x:x,y:y} 
} 
 
// 正确
var newPoint = addPoints({x:3,y:4},{x:5,y:1})  
 
// 错误 
// var newPoint2 = addPoints({x:1},{x:4,y:3})


/*
    类型别名
*/
type UserType = {
    name:string,
    email:string,
    phoneNumber:string
}

let hui:UserType ={
    name:"huishao",
    email:"",
    phoneNumber:"111"
}






